home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
vtkerma1.arc
/
MSSEND.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-02-13
|
33KB
|
1,121 lines
PAGE 59, 132
TITLE MSSEND -- Module to Send files
; Update 13 Jan 86
IF1
%OUT >> Starting pass 1
ELSE
%OUT >> Starting pass 2
ENDIF
PUBLIC spar, rpar, error, error1, nout, send, flags, trans, pack
PUBLIC dodec, doenc, curchk, inichk, packlen, send11
INCLUDE msdefs.h
spmin equ 20 ; Minimum packet size.
spmax equ 94 ; Maximum packet size.
datas segment public 'datas'
extrn DTA:byte, data:byte, fcb:byte, cpfcb:byte, filbuf:byte
extrn decbuf:byte, chrcnt:word, bufpnt:word, comand:byte
extrn rptq:byte, origr:byte, rptct:byte, rptval:byte
flags flginfo <>
trans trinfo <>
pack pktinfo <>
crlf db cr,lf,'$'
erms14 db 'Unable to receive an acknowledgment$'
erms15 db '? File not found',cr,lf,'$'
remmsg1 db 'Remote '
Program_name
db ': File not found$'
erms20 db 'Remote '
Program_name
db ': Unable to send init packet$'
erms21 db 'Remote '
Program_name
db ': Unable to send file header$'
erms22 db 'Remote '
Program_name
db ': Unable to send data$'
erms23 db 'Remote '
Program_name
db ': Unable to send end-of-file packet$'
erms24 db 'Remote '
Program_name
db ': Unable to send break packet$'
infms2 db cr,' Sending: In progress$'
infms3 db 'Completed$'
infms4 db 'Failed$'
infms6 db 'Interrupted$'
infms7 db cr,' Percent transferred: 100%$'
filhlp db ' Input file spec (possibly wild)$'
filmsg db ' File name to use on target system or confirm with'
db ' carriage return$'
curchk db 0 ; Use to store checksum length.
inichk db 1 ; Original or set checksum length.
chrptr dw ? ; Position in character buffer.
fcbpt dw ? ; Position in FCB.
datptr dw ? ; Position in packet data buffer.
siz dw ? ; Size of data from gtchr.
temp dw 0
temp4 dw 0
sendas dw 50 dup(0) ; Buffer for file name.
difnam db 0 ; Send under different name?
difsiz db 0 ; Size of new file name.
asmsg db ' as $'
datas ends
code segment public
EXTRN serini:near, serrst:near, comnd:near, init:near, EOT_bells:NEAR
EXTRN spack:near, rpack:near, gtnfil:near, gtchr:near, ClearL:NEAR
EXTRN getfil:near, clrfln:near, cxmsg:near
EXTRN encode:near, nulref:near, decode:near, nulr:near
EXTRN errpack:near, updrtr:near, clrmod:near, fcbcpy:near
EXTRN perpos:near, Show_error:NEAR, Say_aborted:NEAR
EXTRN Show_status:NEAR, Show_retries:NEAR, Show_packets:NEAR
EXTRN Close_transfer_screen:NEAR
assume cs:code,ds:datas
; This routine sets up the data for init packet (either the
; Send_init or ACK packet).
RPAR PROC NEAR
mov ah,trans.rpsiz ; Get the receive packet size.
add ah,' ' ; Add a space to make it printable.
mov [bx],ah ; Put it in the packet.
mov ah,trans.rtime ; Get the receive packet time out.
add ah,' ' ; Add a space.
mov 1[bx],ah ; Put it in the packet.
mov ah,trans.rpad ; Get the number of padding chars.
add ah,' '
mov 2[bx],ah ; Put it in the packet.
mov ah,trans.rpadch ; Get the padding char.
add ah,100O ; Uncontrol it.
and ah,7FH
mov 3[bx],ah ; Put it in the packet.
mov ah,trans.reol ; Get the EOL char.
add ah,' '
mov 4[bx],ah ; Put it in the packet.
mov ah,trans.rquote ; Get the quote char.
mov 5[bx],ah ; Put it in the packet.
mov ah,trans.ebquot ; Get 8-bit quote char. [21b]
mov 6[bx],ah ; Add it to the packet. [21b]
mov ah,trans.chklen ; Length of checksum.
add ah,48 ; Make into a real digit.
mov 7[bx],ah
mov ah,rptq ; Repeat quote char.
cmp ah,0 ; Null means no.
jne rpar0
mov ah,' ' ; Send a blank instead.
rpar0: mov 8[bx],ah
mov ah,trans.rcaps ; Capabilities
add ah,' ' ; Printable
mov 9[bx],ah ; Set them up
mov ah, 10 ; Ten pieces of data
ret
RPAR ENDP
; This routine reads in all the send_init packet information.
SPAR PROC NEAR
cmp ax,1
jge sparx
mov ah,dspsiz ; Data not supplied by host, use default.
jmp sparx2
sparx: mov temp4,ax ; Save the number of arguments.
mov ah,trans.spsiz
cmp ah,dspsiz ; Is current value the default?
jne sparx2 ; No, assume changed by user.
mov ah,[bx] ; Get the max packet size.
sub ah,' ' ; Subtract a space.
cmp ah,spmin ; Can't be below the minimum.
jge sparx1
mov ah,spmin
jmp sparx2
sparx1: cmp ah,spmax ; Or above the maximum.
jle sparx2
mov ah,spmax
sparx2: mov trans.spsiz,ah ; Save it.
mov ax,temp4
cmp al,2 ; Fewer than two pieces?
jge spar0
mov ah,dstime ; Data not supplied by host, use default.
jmp spar02
spar0: mov ah,trans.stime
cmp ah,dstime ; Is current value the default?
jne spar02 ; No, assume changed by user.
mov ah,1[bx] ; Get the timeout value.
sub ah,' ' ; Subtract a space.
cmp ah,0
ja spar01 ; Must be non-negative.
mov ah,0
spar01: cmp ah,trans.rtime ; Same as other side's timeout.
jne spar02
add ah,5 ; If so, make it a little different.
spar02: mov trans.stime,ah ; Save it.
mov ax,temp4
cmp al,3 ; Fewer than three pieces?
jge spar1
mov ah,dspad ; Data not supplied by host, use default.
jmp spar11
spar1: mov ah,trans.spad
cmp ah,dspad ; Is current value the default?
jne spar11 ; No, assume changed by user.
mov ah,2[bx] ; Get the number of padding chars.
sub ah,' '
cmp ah,0
ja spar11 ; Must be non-negative.
mov ah,0
spar11: mov trans.spad,ah
mov ax,temp4
cmp al,4 ; Fewer than four pieces?
jge spar2
mov ah,dspadc ; Data not supplied by host, use default.
jmp spar21
spar2: mov ah,trans.spadch
cmp ah,dspadc ; Is current value the default?
jne spar21 ; No, assume changed by user.
mov ah,3[bx] ; Get the padding char.
add ah,100O ; Re-controlify it.
and ah,7FH
cmp ah,del ; Delete?
je spar21 ; Yes, then it's OK.
cmp ah,0
jge spar20
mov ah,0 ; Below zero is no good.
jmp spar21 ; Use zero (null).
spar20: cmp ah,31 ; Is it a control char?
jle spar21 ; Yes, then OK.
mov ah,0 ; No, use null.
spar21: mov trans.spadch,ah
mov ax,temp4
cmp al,5 ; Fewer than five pieces?
jge spar3
mov ah,dseol ; Data not supplied by host, use default.
jmp spar31
spar3: mov ah,trans.seol
cmp ah,dseol ; Is current value the default?
jne spar31 ; No, assume changed by user.
mov ah,4[bx] ; Get the EOL char.
sub ah,' '
cmp ah,0
jge spar30 ; Cannot be negative.
mov ah,cr ; If it is, use default of carriage return.
jmp spar31
spar30: cmp ah,31 ; Is it a control char?
jle spar31 ; Yes, then use it.
mov ah,cr ; Else, use the default.
spar31: mov trans.seol,ah
mov ax,temp4
cmp al,6 ; Fewer than six pieces?
jge spar4
mov ah,dsquot ; Data not supplied by host, use default.
jmp spar41
spar4: mov ah,trans.squote
cmp ah,dsquot ; Is current value the default?
jne spar41 ; No, assume changed by user.
mov ah,5[bx] ; Get the quote char.
cmp ah,' ' ; Less than a space?
jge spar40
mov ah,dsquot ; Yes, use default.
jmp spar41
spar40: cmp ah,'~' ; Must also be less then a tilde.
jle spar41
mov ah,dsquot ; Else, use default.
spar41: mov trans.squote,ah
cmp al,7 ; Fewer than seven pieces? [21b begin]
jge spar5
mov trans.ebquot,'Y' ; Data not supplied by host, use default.
jmp spar51
spar5: mov ah,6[bx] ; Get other sides 8-bit quote request.
call doquo ; And set quote char. [21b end]
spar51: cmp al,8 ; Fewer than eight pieces?
jge spar6
mov trans.chklen,1
jmp spar61
spar6: mov ah,inichk
mov trans.chklen,ah ; Checksum length we really want to use.
mov ah,7[bx] ; Get other sides checksum length.
call dochk ; Determine what size to use.
spar61: mov rptq,0 ; Set this up
cmp al,9 ; Fewer than nine pieces?
jl spar71 ; Fewer, use default we just set up
mov ah,8[bx] ; Get other side's repeat count prefix
mov ch,drpt
call dorpt
spar71: cmp al,10 ; Fewer than ten pieces?
jge spar8 ; Have them ...
mov trans.scaps,0 ; Say no special caps
ret
spar8: mov ah,9[bx] ; Pick up the value we got
sub ah,' ' ; Convert from printable
mov trans.scaps, ah ; Store in Trans structure
ret
SPAR ENDP
; Set 8-bit quote character based on my capabilities and the other
; Kermit's request. [21b]
DOQUO PROC NEAR
cmp trans.ebquot,'N' ; Can I do 8-bit quoting at all?
je dq3 ; No - so forget it.
cmp trans.ebquot,'Y' ; Can I do it if requested?
jne dq0 ; No - it's a must that I do it.
mov trans.ebquot,ah ; Do whatever he wants.
jmp dq1
dq0: cmp ah,'Y' ; I need quoting - can he do it?
je dq1 ; Yes - then all is settled.
cmp ah,'N' ; No - then don't quote.
je dq3
cmp ah,trans.ebquot ; Both need quoting - chars must match.
jne dq3
dq1: mov ah,trans.ebquot
cmp ah,'Y' ; If Y or N, don't validate prefix.
je dq2
cmp ah,'N'
je dq2
call prechk ; Is it in range 33-62, 96-126?
mov ah,'Y' ; Failed, don't do quoting.
nop
cmp ah,trans.rquote ; Same prefix?
je dq3 ; Not allowed, so don't do quoting.
cmp ah,trans.squote ; Same prefix here?
je dq3 ; This is illegal too.
mov trans.ebquot,ah ; Remember what we decided on.
dq2: ret
dq3: mov trans.ebquot,'N' ; Quoting will not be done.
ret
DOQUO ENDP
; Check if prefix in AH is in the proper range: 33-62, 96-126.
; RSKP if so else RETURN.
prechk: cmp ah,33
jge prec0 ; It's above 33.
ret
prec0: cmp ah,62
jg prec1
jmp rskp ; And below 62. OK.
prec1: cmp ah,96
jge prec2 ; It's above 96.
ret
prec2: cmp ah,126
jg prec3
jmp rskp ; And below 126. OK.
prec3: ret
; Set checksum length.
dochk: cmp ah,'1' ; Must be 1, 2, or 3.
jl doc1
cmp ah,'3'
jle doc2
doc1: mov ah,'1'
doc2: sub ah,48 ; Don't want it printable.
cmp ah,trans.chklen ; Do we want the same thing?
je dochk0 ; Yes, then we're done.
mov trans.chklen,1 ; No, use single character checksum.
dochk0: ret ; Just return for now.
; Set repeat count quote character. The one used must be different than
; the control and eight-bit quote characters. Also, both sides must
; use the same character.
dorpt: call prechk ; Is it in the valid range?
mov ah,0 ; No, don't use their value.
nop
cmp ah,trans.squote ; Same as the control quote char?
je dorpt0 ; Yes, that's illegal, no repeats.
cmp ah,trans.rquote ; How about this one?
je dorpt0 ; No good.
cmp ah,trans.ebquot ; Same as eight bit quote char?
je dorpt0 ; Yes, that's illegal too, no repeats.
cmp ah,ch ; Are we planning to use the same char?
jne dorpt0 ; No, that's no good either.
mov rptq,ch ; Use repeat quote char now.
dorpt0: ret
; Send command
SEND PROC NEAR
mov comand.cmcr,0 ; Filename must be specified.
mov difnam,0 ; Assume we'll use original filename.
mov flags.wldflg,0 ; Re-initialize every time.
mov ah,cmifi ; Parse an input file spec.
mov dx,offset fcb ; Give the address for the FCB.
mov bx,offset filhlp ; Text of help message.
call comnd
jmp RSkp ; Give up on bad parse.
cmp flags.wldflg,0FFH ; Any wildcards seen?
je send1 ; Yes, get a confirm.
mov bx,offset sendas ; See if want to send file under dif name.
mov dx,offset filmsg ; In case user needs help.
mov ah,cmtxt
call comnd
jmp RSkp
cmp ah,0 ; Different name supplied?
je send0a ; No
mov difnam,1 ; Yes - send different filename.
mov difsiz,ah ; Remember length of new name.
jmp SHORT send10 ; Join common code
send0a: mov ah,sfirst ; Get the first file.
mov dx,offset fcb
int dos ; Make sure file exists
cmp al,0FFH ; Any found?
jne send10 ; Yes, move on
mov ah,prstr ; No, complain
mov dx,offset erms15
int dos
jmp rskp
send1: mov ah,cmcfm
call comnd ; Get a confirm.
jmp r ; Didn't get a confirm.
Send10: call serini ; Initialize serial port. [14]
call Init ; Clear the line and initialize the buffers
mov dx, OFFSET Infms2 ; Sending: In progress
call Show_status ; Say what mode we are in
call Send11 ; Call our routine to send the file
nop ; He skips
nop
nop
jmp RSkp ; Return skip
Send11: mov flags.droflg,0 ; Reset flags from fn parsing. [21a]
mov flags.nmoflg,0 ; Reset flags from fn parsing. [21a]
mov ah,sfirst ; Get the first file.
mov dx,offset fcb
int dos
cmp al,0FFH ; Any found?
jne send12
cmp pack.state,'R' ; was this from a remote GET?
jne sen11a ; no, print error and continue
mov bx,offset remmsg1 ; else get error message
call errpack ; go complain
jmp abort ; and abort this
sen11a: mov ah,prstr
mov dx,offset erms15
int dos
jmp rskp
PUBLIC Send12
send12: cmp flags.wldflg,0 ; Any wildcards. [7 start]
je send16 ; Nope, so no problem.
mov bx,offset fcb ; Remember what FCB looked like.
mov di,offset cpfcb
mov cl,37 ; Size of FCB.
call fcbcpy
mov di,offset fcb+1 ; Copy filename from DTA to FCB.
mov bx,offset DTA+1
mov cl,11
call fcbcpy ; [7 end]
send16: mov pack.pktnum,0 ; Set the packet number to zero.
mov pack.numtry,0 ; Set the number of tries to zero.
mov pack.numpkt,0 ; Set the number of packets to zero.
mov pack.numrtr,0 ; Set the number of retries to zero.
mov pack.state,'S' ; Set the state to send initiate.
mov dx, OFFSET Infms2 ; Sending: In progress
call Show_status ; Say what mode we are in
call Show_packets ; Display packet count
call ClearL ; Make sure display looks right
Send2: call Show_packets ; Display packet count
cmp pack.state,'D' ; Are we in the data send state?
jne send3
call sdata
jmp send2
send3: cmp pack.state,'F' ; Are we in the file send state?
jne send4
call sfile ; Call send file.
jmp send2
send4: cmp pack.state,'Z' ; Are we in the EOF state?
jne send5
call seof
jmp send2
send5: cmp pack.state,'S' ; Are we in the send initiate state?
jne send6
call sinit
jmp send2
send6: cmp pack.state,'B' ; Are we in the eot state?
jne send7
call seot
jmp send2
send7: cmp pack.state,'C' ; Are we in the send complete state?
jne send8
cmp Flags.RemFlg, 0 ; remote mode?
jne Send9a ; yes, no printing
cmp Flags.cxzflg, 0 ; completed normally?
jne Send7a ; no, don't bother with this
call PerPos ; Note that we are now 100% done
mov ah, PrStr
mov dx, OFFSET infms7
int Dos
mov dx, OFFSET InfMs3 ; Message saying success
jmp SHORT Send7b
Send7a: mov dx, OFFSET infms6 ; Say was interrupted
Send7b: call Show_status ; Display the message, whatever it is
call EOT_bells ; Make noise if enabled
jmp SHORT Send9
; Hit some error, should have been already noted onscreen
send8: mov dx,offset infms4 ; Plus a little cuteness
call Show_status ; Say we failed
send9: call Close_transfer_screen
Send9a: jmp rskp
SEND ENDP
; Send routines
; Send initiate
SINIT PROC NEAR
cmp pack.numtry,imxtry ; Have we reached the maximum number of tries?
jl sinit2
mov dx,offset erms14
call Show_error
mov bx,offset erms20
call errpack ; Send error packet just in case.
jmp abort ; Change the state to abort.
sinit2: inc pack.numtry ; Save the updated number of tries.
mov bx,offset data ; Get a pointer to our data block.
call rpar ; Set up the parameter information.
xchg ah,al
mov ah,0
mov pack.argbk1,ax ; Save the number of arguments.
mov ax,pack.numpkt ; Get the packet number.
mov pack.argblk,ax
mov ah,trans.chklen
mov curchk,ah ; Store checksum length we want to use.
mov trans.chklen,1 ; Send init checksum is always 1 char.
mov ah,'S' ; Send initiate packet.
call spack ; Send the packet.
jmp abort
call rpack ; Get a packet.
jmp sini23 ; Trashed packet don't change state, retry.
push ax
mov ah,curchk
mov trans.chklen,ah ; Checksum length we want to use.
pop ax
cmp ah,'Y' ; ACK?
jne sinit3 ; If not try next.
mov ax,pack.pktnum ; Get the packet number.
cmp ax,pack.argblk ; Is it the right packet number?
je sini22
ret ; If not try again.
sini22: inc ax ; Increment the packet number.
and ax,3FH ; Turn off the two high order bits.
mov pack.pktnum,ax ; Save modulo 64 of the number.
inc pack.numpkt ; Increment the number of packets.
mov ax,pack.argbk1 ; Get the number of pieces of data.
mov bx,offset data ; Pointer to the data.
call spar ; Read in the data.
call packlen ; Get max send packet size. [21b]
mov ah,pack.numtry ; Get the number of tries.
mov pack.oldtry,ah ; Save it.
mov pack.numtry,0 ; Reset the number of tries.
mov pack.state,'F' ; Set the state to file send.
call getfil ; Open the file.
jmp abort ; Something is wrong, die.
ret
%OUT >> About half way through source file
sini23: mov ah,curchk ; Restore desired checksum length.
mov trans.chklen,ah
call updrtr ; Update retry counter.
ret ; And retry.
sinit3: cmp ah,'N' ; NAK?
jne sinit4 ; If not see if its an error.
inc pack.numrtr ; Increment the number of retries
jmp Show_retries ; Show the number of retries onscreen
sinit4: cmp ah,'E' ; Is it an error packet.
jne sinit5
call error
sinit5: jmp abort
SINIT ENDP
; Send file header
SFILE PROC NEAR
cmp pack.numtry,maxtry ; Have we reached the maximum number of tries?
jl sfile1
mov dx,offset erms14
call Show_error
mov bx,offset erms21
call errpack ; Send error packet just in case.
jmp abort ; Change the state to abort.
sfile1: inc pack.numtry ; Increment it.
mov flags.cxzflg,0 ; Clear ^X,^Z flag.
mov datptr,offset data ; Get a pointer to our data block.
mov bx,offset fcb+1 ; Pointer to file name in FCB.
mov fcbpt,bx ; Save position in FCB.
mov cl,0 ; Counter for chars in file name.
mov ch,0 ; Counter for number of chars in FCB.
sfil11: cmp ch,8H ; Ninth char?
jne sfil12
mov ah,'.'
mov bx,datptr
mov [bx],ah ; Put dot in data packet.
inc bx
mov datptr,bx ; Save new position in data packet.
inc cl
sfil12: inc ch
cmp ch,0CH ; Twelve?
jns sfil13
mov bx,fcbpt
mov ah,[bx] ; Get char of filename.
inc bx
mov fcbpt,bx ; Save position in FCB.
cmp ah,'!' ; Is it a good char?
jl sfil11 ; If not, get the next.
mov bx,datptr
mov [bx],ah ; Put char in data buffer.
inc cl ; Increment counter.
inc bx
mov datptr,bx ; Save new position.
jmp sfil11 ; Get another char.
sfil13: mov ch,0
cmp flags.remflg,0 ; remote mode?
jne sfil13a ; yes, no printing.
push cx ; Don't forget the size.
mov bx,datptr
mov ah,'$'
mov [bx],ah ; Put dollar sign for printing.
call clrfln
mov ah,prstr
mov dx,offset data ; Print file name.
int dos
pop cx
sfil13a:cmp difnam,0 ; Sending file under different name.
je sfl13x ; No, so don't give new name.
call newfn
sfl13x: call doenc ; Do encoding.
mov ax,pack.pktnum ; Get the packet number.
mov pack.argblk,ax
mov ah,'F' ; File header packet.
call spack ; Send the packet.
jmp abort
call rpack ; Get a packet.
jmp tryagn ; Trashed packet don't change state, retry.
call dodec ; Do all decoding.
cmp ah,'Y' ; ACK?
jne sfile2 ; If not try next.
mov ax,pack.pktnum ; Get the packet number.
cmp ax,pack.argblk
je sfil14
ret ; If not hold out for the right one.
sfil14: inc ax ; Increment the packet number.
and ax,3FH ; Turn off the two high order bits.
mov pack.pktnum,ax ; Save modulo 64 of the number.
inc pack.numpkt ; Increment the number of packets.
mov ah,pack.numtry ; Get the number of tries.
mov pack.oldtry,ah ; Save it.
mov pack.numtry,0 ; Reset the number of tries.
sfil15: mov ah,0 ; Get a zero.
mov bx,offset fcb
add bx,20H
mov [bx],ah ; Set the record number to zero.
; mov flags.eoflag,ah ; Indicate not EOF. (Done in GETFIL).
mov ah,0FFH
mov flags.filflg,ah ; Indicate file buffer empty.
call gtchr
jmp sfil16 ; Error go see if its EOF.
nop
jmp sfil17 ; Got the chars, proceed.
sfil16: cmp ah,0FFH ; Is it EOF?
je sfl161
jmp abort ; If not give up.
sfl161: mov ah,'Z' ; Set the state to EOF.
mov pack.state,ah
ret
sfil17: mov siz,ax
call Send_attribute ; Maybe send an attribute packet
mov pack.state,'D' ; Set the state to data send.
ret
Send_attribute:
ret ; NOP for now
sfile2: cmp ah,'N' ; NAK?
jne sfile3 ; Try if error packet.
inc pack.numrtr ; Increment the number of retries
call Show_retries
mov ax,pack.pktnum ; Get the present packet number.
inc ax ; Increment.
and ax,03FH ; Account for wraparound. [18]
cmp ax,pack.argblk ; Is the packet's number one more than now?
jz sfil14 ; Just as good as a ACK; go to the ACK code.
ret ; If not go try again.
sfile3: cmp ah,'E' ; Is it an error packet.
jne sfile4
call error
sfile4: jmp abort
SFILE ENDP
; Send data
SDATA PROC NEAR
cmp flags.cxzflg,0 ; Have we seen ^X or ^Z?
je sdata2 ; Nope, just continue.
cmp flags.cxzflg,'C' ; Stop it all? [25]
jne sdata1 ; It was a ^X or ^Z.
call Say_aborted ; Note this "error" onscreen
mov pack.state,'A' ; It was a ^C -- abort [25]
ret
sdata1: mov pack.state,'Z' ; Else, abort sending the file.
ret
sdata2: cmp pack.numtry,maxtry ; Have we reached the maximum number of tries?
jl sdata3
mov dx,offset erms14
call Show_error ; Display error message
mov bx,offset erms22
call errpack ; Send error packet just in case.
jmp abort ; Change the state to abort.
sdata3: inc pack.numtry ; Increment it.
mov datptr,offset data ; Get a pointer to our data block.
mov chrptr,offset filbuf ; Pointer to chars to be sent.
mov cx,siz ; number to transfer
mov si,chrptr ; source of characters
mov di,datptr ; destination
cmp flags.eofcz,0 ; stopping on ctl-z's?
jz sdata6 ; no, do blind copy
sdata4: lodsb ; get a byte
cmp al,'Z'-40H ; is it a ctl-z?
je sdata5 ; yes, break loop
stosb ; else copy it
loop sdata4 ; and keep going
sdata5: mov ax,siz ; size to send
sub ax,cx ; minus actually sent...
jmp short sdata7
sdata6: rep movsb ; just copy data
mov ax,siz ; this is how many were moved
sdata7: mov pack.argbk1,ax
mov ax,pack.pktnum ; Get the packet number.
mov pack.argblk,ax
mov ah,'D' ; Data packet.
call spack ; Send the packet.
jmp tryagn ; if can't send it, retry before giving up
call rpack ; Get a packet.
jmp tryagn ; Trashed packet don't change state, retry.
call dodec ; Do all decoding.
cmp ah,'Y' ; ACK?
jne sdat14 ; If not try next.
mov ax,pack.pktnum ; Get the packet number.
cmp ax,pack.argblk ; Is it the right packet number?
jz sdata8
ret ; If not hold out for the right one.
sdata8: inc ax ; Increment the packet number.
and ax,3FH ; Turn off the two high order bits.
mov pack.pktnum,ax ; Save modulo 64 of the number.
inc pack.numpkt ; Increment the number of packets.
mov ah,pack.numtry ; Get the number of tries.
mov pack.oldtry,ah ; Save it.
mov pack.numtry,0 ; Reset the number of tries.
cmp pack.argbk1,1 ; Does the ACK contain data?
jne sdat11 ; Nope, so continue.
mov bx,offset data ; If yes, check the data field.
mov ah,[bx] ; Pick it up.
cmp ah,'X' ; Other side requests ^X?
jne sdata9 ; Nope.
jmp sdat10 ; And leave.
sdata9: cmp ah,'Z' ; Other side requests ^Z?
jne sdat11 ; Nope.
sdat10: mov flags.cxzflg,ah ; Yes remember it.
mov pack.state,'Z' ; Abort sending file(s).
ret
sdat11: call gtchr
jmp sdat12 ; Error go see if its EOF.
mov siz,ax ; Save the size of the data gotten.
ret
sdat12: cmp ah,0FFH ; Is it EOF?
je sdat13
jmp abort ; If not give up.
sdat13: mov pack.state,'Z' ; Set the state to EOF.
ret
sdat14: cmp ah,'N' ; NAK?
jne sdat15 ; See if is an error packet.
inc pack.numrtr ; Increment the number of retries
call Show_retries ; Display it
mov ax,pack.pktnum ; Get the present packet number.
inc ax ; Increment.
and ax,03FH ; Account for wraparound. [18]
cmp ax,pack.argblk ; Is the packet's number one more than now?
jz sdata8 ; Just as good as ACK; goto ACK code.
ret ; If not go try again.
sdat15: cmp ah,'E' ; Is it an error packet.
jne sdat16
call error
sdat16: jmp abort
SDATA ENDP
; Send EOF
SEOF PROC NEAR
cmp pack.numtry,maxtry ; Have we reached the maximum number of tries?
jl seof1
mov dx,offset erms14
call Show_error ; Display an error message
mov bx,offset erms23
call errpack ; Send error packet just in case.
jmp abort ; Change the state to abort.
seof1: inc pack.numtry ; Increment it.
mov ax,pack.pktnum ; Get the packet number.
mov pack.argblk,ax
mov pack.argbk1,0 ; No data.
cmp flags.cxzflg,0 ; Seen a ^X or ^Z?
je seof11 ; Nope, send normal EOF packet.
mov bx,offset data ; Get data area of packet.
mov ah,'D' ; Use "D" for discard.
mov [bx],ah ; And add it to the packet.
mov pack.argbk1,1 ; Set data size to 1.
seof11: mov cx,pack.argbk1 ; Put size in CX.
call doenc ; Encode the packet.
mov ah,'Z' ; EOF packet.
call spack ; Send the packet.
jmp abort
call rpack ; Get a packet.
jmp tryagn ; Trashed packet don't change state, retry.
call dodec ; Do decoding.
cmp ah,'Y' ; ACK?
jne seof2 ; If not try next.
mov ax,pack.pktnum ; Get the packet number.
cmp ax,pack.argblk ; Is it the right packet number?
jz seof12
ret ; If not hold out for the right one.
seof12: inc ax ; Increment the packet number.
and ax,3FH ; Turn off the two high order bits.
mov pack.pktnum,ax ; Save modulo 64 of the number.
inc pack.numpkt ; Increment the number of packets.
mov ah,pack.numtry ; Get the number of tries.
mov pack.oldtry,ah ; Save it.
mov pack.numtry,0 ; Reset the number of tries.
mov ah,closf ; Close the file.
mov dx,offset fcb
int dos
call gtnfil ; Get the next file.
jmp seof13 ; No more.
mov pack.state,'F' ; Set the state to file send.
; Is this right ???????
mov flags.cxzflg,0 ; Reset the flag.
ret
seof13: mov pack.state,'B' ; Set the state to EOT.
ret
seof2: cmp ah,'N' ; NAK?
jne seof3 ; Try and see if its an error packet.
inc pack.numrtr ; Increment the number of retries
call Show_retries ; Display it
mov ax,pack.pktnum ; Get the present packet number.
inc ax ; Increment.
and ax,03FH ; Account for wraparound. [18]
cmp ax,pack.argblk ; Is the packet's number one more than now?
jz seof12 ; Just as good as a ACK; go to the ACK code.
ret ; If not go try again.
seof3: cmp ah,'E' ; Is it an error packet?
jne seof4
call error
seof4: jmp abort
SEOF ENDP
; Send EOT
SEOT PROC NEAR
cmp pack.numtry,maxtry ; Have we reached the maximum number of tries?
jl seot1
mov dx,offset erms14
call Show_error ; Display error
mov bx,offset erms24
call errpack ; Send error packet just in case.
jmp abort ; Change the state to abort.
seot1: inc pack.numtry ; Increment it.
mov ax,pack.pktnum ; Get the packet number.
mov pack.argblk,ax
mov pack.argbk1,0 ; No data.
mov cx,pack.argbk1
call doenc ; Encode packet.
mov ah,'B' ; EOF packet.
call spack ; Send the packet.
jmp abort
call rpack ; Get a packet.
jmp tryagn ; Trashed packet don't change state, retry.
call dodec ; Decode packet.
cmp ah,'Y' ; ACK?
jne seot2 ; If not try next.
mov ax,pack.pktnum ; Get the packet number.
cmp ax,pack.argblk ; Is it the right packet number?
jz seot12
ret ; If not hold out for the right one.
seot12: inc ax ; Increment the packet number.
and ax,3FH ; Turn off the two high order bits.
mov pack.pktnum,ax ; Save modulo 64 of the number.
inc pack.numpkt ; Increment the number of packets.
mov ah,pack.numtry ; Get the number of tries.
mov pack.oldtry,ah ; Save it.
mov pack.numtry,0 ; Reset the number of tries.
mov pack.state,'C' ; Set the state to file send.
ret
seot2: cmp ah,'N' ; NAK?
jne seot3 ; Is it error.
inc pack.numrtr ; Increment the number of retries
call Show_retries ; Display it
mov ax,pack.pktnum ; Get the present packet number.
inc ax ; Increment.
and ax,03FH ; Account for wraparound. [18]
cmp ax,pack.argblk ; Is the packet's number one more than now?
jz seot12 ; Just as good as a ACK; go to the ACK code.
ret ; If not go try again.
seot3: cmp ah,'E' ; Is it an error packet.
jne seot4
call error
seot4: jmp abort
SEOT ENDP
tryagn: call updrtr
ret
newfn: mov ah,prstr
mov dx,offset asmsg
int dos
mov ah,dconio
mov si,offset sendas ; Buffer where the name is.
mov di,offset data
mov ch,0
mov cl,difsiz ; Length of name.
newf0: lodsb ; Get a char.
cmp al,61H
jb newf1 ; Leave alone if less than 'a'?
cmp al,7AH
ja newf1 ; Leave alone if over 'z'.
sub al,20H ; Uppercase the letters.
newf1: stosb
mov dl,al
cmp flags.remflg,0 ; should we print?
jne newf2 ; no, we're in remote mode.
int dos ; Print them.
newf2: loop newf0
mov ch,0
mov cl,difsiz ; Reset the length field.
ret
; Do encoding. Expectx CX to be the data size.
doenc: jcxz doen0
mov chrcnt,cx ; Number of chars in filename.
mov bx,offset data ; Source of data.
mov bufpnt,bx
mov bx,offset nulref ; Null routine for refilling buffer.
mov ah,rptq
mov origr,ah ; Save repeat prefix here.
mov rptct,1 ; Number of times char is repeated.
mov rptval,0 ; Value of repeated char.
call encode ; Make a packet with size in AX.
nop
nop
nop
mov pack.argbk1,ax ; Save number of char in filename.
mov cx,ax
call movpak ; Move to data part of packet.
doen0: ret
; CX is set before this is called.
movpak: push es
mov ax,ds
mov es,ax
mov si,offset filbuf ; Move from here
mov di,offset data ; to here
repne movsb
pop es
ret
; Do decoding.
dodec: cmp pack.argbk1,0
je dodc0
push ax ; Save packet size.
mov cx,pack.argbk1 ; Size of data.
mov bx,offset data ; Address of data.
mov ax,offset nulr ; Routine to dump buffer (null routine).
mov bufpnt,offset decbuf ; Where to put output.
mov chrcnt,80H ; Buffer size.
call decode
nop
nop
nop
call decmov ; Move decoded data back to "data" buffer.
pop ax
dodc0: ret
; Move decoded data from decode buffer back to "data".
decmov: push si
push di
push es
mov ax,ds
mov es,ax
mov cx,bufpnt ; Last char we added.
sub cx,offset decbuf ; Get actual number of characters.
mov pack.argbk1,cx ; Remember size of real data.
lea si,decbuf ; Data is here.
lea di,data ; Move to here.
repne movsb ; Copy the data.
pop es
pop di
pop si
ret
; Abort
ABORT PROC NEAR
mov pack.state,'A' ; Otherwise abort.
ret
ABORT ENDP
; This is where we go if we get an error packet. A call to ERROR
; positions the cursor and prints the message. A call to ERROR1
; just prints a CRLF and then the message. [8]
ERROR PROC
mov pack.state,'A' ; Set the state to abort.
mov bx,pack.argbk1 ; Get the length of the data.
add bx,offset data ; Get to the end of the string.
mov ah,'$' ; Put a dollar sign at the end.
mov [bx],ah
mov dx,offset data ; The error message
jmp Show_error ; Display the message and beep
ERROR ENDP
Error1 PROC
mov bx,pack.argbk1 ; Get the length of the data.
add bx,offset data ; Get to the end of the string.
mov ah,'$' ; Put a dollar sign at the end.
mov [bx],ah
mov ah, PrStr ; Print the error message.
mov dx, OFFSET data
int dos
mov dx, OFFSET crlf
int dos
ret
Error1 ENDP
; Set the maximum data packet size. [21b]
PACKLEN PROC NEAR
mov ah,trans.spsiz ; Maximum send packet size.
sub ah,4 ; Size minus control info.
sub ah,trans.chklen ; And minus checksum chars.
sub ah,2 ; Leave room at end: 2 for possible #X.
cmp trans.ebquot,'N' ; Doing 8-bit quoting?
je pack0 ; Nope so we've got our size.
cmp trans.ebquot,'Y'
je pack0 ; Not doing it in this case either.
sub ah,1 ; Another 1 for 8th-bit quoting.
pack0: cmp rptq,0 ; Doing repeat character quoting?
je pack1 ; Nope, so that's all for now.
sub ah,2 ; Another 2 for repeat prefix.
pack1: mov trans.maxdat,ah ; Save max length for data field.
ret
PACKLEN ENDP
; Print the number in AX on the screen in decimal rather that hex. [19a]
NOUT PROC NEAR
cmp flags.xflg,1 ; Writing to screen? [21c]
je nout1 ; Yes, just leave. [21c]
push ax
push dx
mov temp,10 ; Divide quotient by 10.
mov dx,0 ; High order word should be zero.
div temp ; AX <-- Quo, DX <-- Rem.
cmp ax,0 ; Are we done?
jz nout0 ; Yes.
call nout ; If not, then recurse.
nout0: add dl,'0' ; Make it printable.
mov temp,ax
mov ah,conout
int dos
mov ax,temp
pop dx
pop ax
nout1: ret ; We're done. [21c]
NOUT ENDP
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end